set script_scanerThreadInit {
	set config(inc_log)       "./inc/log.tcl"
	set config(inc_utils)     "./inc/utils.tcl"
	set config(script_logger) "./script/loggerInit.tcl"
	set config(script_worker) "./script/workerInit.tcl"
	set config(utils_inet)    "./inc/inet.tcl"

	if {![ file exists $config(inc_log) ]} {
		puts stderr "Can't load $config(inc_log)"
		thread::release
	} else {
		source $config(inc_log)
	}

	set mainThread ""
	set loggerThread ""

	set workersPool {}
	set MAX_WORKERS 5
	set workersInUse {}

	proc init { mainThreadId {workersCount 5}} {
		global mainThread loggerThread
		global config
		global MAX_WORKERS

		if { $mainThreadId == "" || ![ thread::exists $mainThreadId ]} {
			return false
		}
		set mainThread $mainThreadId

		if {![ file exists $config(script_logger) ]} {
			writeLog "Logger script missing ($config(script_logger)). Using native log functions"
		} else {
			source $config(script_logger)
			if {![ info exists script_loggerInit ]} {
				writeLog "Breaking logger script ($config(script_logger)). Using native log functions"
			} else {
				set loggerThread [ thread::create -joinable $script_loggerInit ]
			}
		}

		if {![ file exists $config(utils_inet) ]} {
			writeLog "$config(utils_inet) missing!"
			if {[ thread::exists $loggerThread ]} { thread::release $loggerThread }
			thread::release
		} else {
			source $config(utils_inet)
		}
		source $config(inc_utils)

		if {![ file exists $config(script_worker) ]} {
			writeLog "$config(script_worker) missing!"
			if {[ thread::exists $loggerThread ]} { thread::release $loggerThread }
			thread::release
		} else {
			source $config(script_worker)
			set MAX_WORKERS $workersCount
			spawnWorkers $script_workerInit $MAX_WORKERS
		}
		return true
	}

	proc spawnWorker { script_workerInit } {
		global loggerThread
		global workersPool
		if {![ info exists loggerThread ]} {
			return false
		}
		set newWorker [ thread::create -joinable $script_workerInit ]
		thread::send -async $newWorker [ list init [ thread::id ] $loggerThread ]
		lappend workersPool $newWorker
		return true
	}

	proc spawnWorkers { script_workerInit maxWorkers } {
		global loggerThread
		for { set i 0 } { $i < $maxWorkers } { incr i } {
			if {![ spawnWorker $script_workerInit ]} {
				writeLog "worker not spawned"
			}
		}
		return true
	}

	proc scanNetwork { netAddress } {
		global loggerThread
		global workersPool workersInUse MAX_WORKERS
		set addressCount [ expr [ inet_hostCount $netAddress ] - 2 ]
		set firstHostAddress [ inet_firstHost $netAddress ]

		if { $addressCount < $MAX_WORKERS } {
			set usedWorkersCount $addressCount
			set hostPerWorker 1
			set unscannedCount 0
		} else {
			set usedWorkersCount $MAX_WORKERS
			set hostPerWorker [ expr $addressCount / $MAX_WORKERS ]
			set unscannedCount [ expr $addressCount % $MAX_WORKERS ]
		}

		for { set i 0 } { $i < $usedWorkersCount } { incr i } {
			set firstHost [ inet_ntoa [ expr [ inet_aton $firstHostAddress ] + $hostPerWorker * $i ] ]
			# обработка случая, когда хостов в сети меньше, чем кол-во воркеров
			set nextWorker [ lindex $workersPool $i ]
			thread::send -async $nextWorker [ list scanNetwork $firstHost $hostPerWorker ]
			lappend workersInUse $nextWorker
		}
		if { $unscannedCount != 0 } {
			set firstHost [ inet_ntoa [ expr [ inet_aton $firstHostAddress ] + $hostPerWorker * $i ] ]
			thread::send -async [ lindex $workersPool [ expr $usedWorkersCount - 1 ] ] [ list scanNetwork $firstHost $unscannedCount ]
		}
	}

	proc onHostAlive { hostAddress } {
		global loggerThread
		writeLog "$hostAddress is up"
	}

	proc onScanningDone { workerThread } {
		global workersPool workersInUse
		global loggerThread
		set workersInUse [ lreplace $workersInUse [lsearch $workersInUse $workerThread] [lsearch $workersInUse $workerThread] ]
		if {[ llength $workersInUse ] == 0} {
			for { set i 0 } { $i < [ llength $workersPool ]} { incr i } {
				set nextWorker [ lindex $workersPool $i ]
				writeDebug "waiting for $nextWorker ([expr [llength $workersPool] - $i - 1 ] left)"
				thread::release $nextWorker
				thread::join $nextWorker
			}
			writeDebug "Scanning done"
			thread::release $loggerThread
			thread::join $loggerThread
			thread::release
		}
	}

	thread::wait
}
